/*
 * Ampl.java
 *
 * Created on April 5, 2005, 3:31 AM
 * November 10, 2005 Renamed to AmplFrontEnd
 */

package portfolio.ampl;

import misellanea.MiscellaneaDB;

import java.net.*;
import java.io.*;
import java.util.Vector;
import javax.swing.JTextArea;
import java.awt.Font;

public class AmplFrontEnd {

    static String last_prompt = "";

    static OutputStream out;
    static PrintStream pout;
    static DataInputStream dis;
    static DataInputStream dos;
    
    ////////////////////////////////////////////////////////////////////////
    static public void main (String [] args)
    {
        String sCmd = null;
        try {
            AmplFrontEnd a = new AmplFrontEnd ("ampl");
            if (a != null) { // test for vital signs
		a.send("option show_stats 1; option display_eps .000001; print $version;\n");
		System.out.println (">"+a.rcv());
                //a.send ("model " + "..\\quadmod\\markowitz.mod" +";\n");
                a.send ("model " + "c:\\ampl\\quadmod\\markowitz.mod" +";\n");
                System.out.println (">"+a.rcv());
            }        
        }
        catch (Exception e) {
            System.err.println (e);
        }    
    }
////////////////////////////////////////////////////////////////////////
    public AmplFrontEnd (String cmd)	throws IOException
    {   
	String[] amplcmd = new String[2];
	amplcmd[0] = cmd;
	amplcmd[1] = "-b";	// turns on block mode, off cr

	Runtime rt = Runtime.getRuntime();
System.err.println("starting " + amplcmd[0]);
	Process p = rt.exec(amplcmd);
System.err.println("started " + amplcmd[0]);
	out = p.getOutputStream();
	pout = new PrintStream(out, true);
	dis = new DataInputStream(System.in);
	dos = new DataInputStream(p.getInputStream());
System.err.println("files opened");

	rcv();	// absorb initial prompt from ampl
    }
/**************************************************************************/
    public String getPrompt() {
	return last_prompt;
    }
/**************************************************************************/
    public void send(String s) 
    {
//System.err.println("send " + s.length() + " [" + s + "]");
	pout.print(s.length() + " " + s);
    }
/*************************************************************************/
    public String rcv()
    {
	byte buf[] = new byte[20000];
	int n, i;
	byte b;
	String s = new String("");

	try {
		while (true) {
			n = 0;
			for (i = 0; (b = dos.readByte()) >= '0' && b <= '9'; i++)
				n = 10 * n + b - '0';
//System.err.println("n = " + n + ", b = [" + b + "]");
			// read n more characters; delete carriage returns.
			for (i = 0; i < n; ) {
				b = dos.readByte();
//System.err.println("b = " + b);
				if (b != '\r')
					buf[i++] = b;
			}
			String s1 = new String(buf, 0, 0, i);
//System.err.println("rcv " + s1.length() + " [" + s1 + "]");
			if (s1.regionMatches(0, "prompt", 0, 6)) {
				last_prompt = s1.substring(s1.indexOf('\n')+1);
				break;
			}
			s = s + s1;
		}
	} catch (IOException e) {
		System.err.println(e + "rcv error");
		return e + "rcv error";
	}
	return s.substring(s.indexOf('\n') + 1);
    }
    /***********************************************************************/
    public void close()
    {
	try {
            if (out != null) out.close();
            if (pout != null) pout.close();
            if (dis != null) dis.close();
            if (dos != null) dos.close();
            out = null; pout = null; dis = null; dos = null;
	} catch (IOException e) {;}
    }/* end method Ampl::close */
    /***************************************************************************/
    public String setAmplSet (String sSetName, Vector vSetParam)
    {
        int iSize = vSetParam.size();
        String sStrSet = new String ("set " + sSetName + " :=");
        
        for (int i = 0; i < iSize; i++) {
            String sTmp = new String (" " + vSetParam.get (i).toString ());
            sStrSet += sTmp; //new String (vSetParam.get (i).toString ()));
            //System.out.println (i+" "+sStrSet); //sSetName);
        }
        sStrSet += ";";
        //System.out.println (sStrSet);
        
        return sStrSet;
    }
    /***************************************************************************/
    public String setAmplParam (String sParamName, Vector vHeaderParam, Vector vRowParam, double [][]dTimeSeries)
    {
        int iRow        = dTimeSeries.length;
        int iColumn     = dTimeSeries [0].length;
        String sParam   = new String ("param " + sParamName + ": ");
        int iHeaderSize = vHeaderParam.size();
        
        for (int i = 0; i < iHeaderSize; i++) {
            String sTmp = new String (" " + vHeaderParam.get (i).toString ());
            sParam += sTmp;
        }
        sParam += " :=\n";
        
        for (int i = 0; i < iRow; i++) {
            sParam += vRowParam.get(i).toString();
            sParam += " ";
            for (int j = 0; j < iColumn; j++) {
                //System.out.print (dTimeSeries [i][j] +" ");
                sParam += dTimeSeries[i][j];
                sParam += " ";
            }
            //System.out.println ();
            sParam += "\n";
        }
        sParam += ";\n";
        //System.out.println (sParam);
        return sParam;
    }
    /***************************************************************************/
    public String setAmplSet2 (String sParamName, Vector vHeaderParam)
    {
        int iRow        = vHeaderParam.size();
 
        String sParam   = new String ("set " + sParamName + " := {");
        int iHeaderSize = vHeaderParam.size();
        
        int i;
        if (iRow > 1) {
            for (i = 0; i < iRow -1; i++) {
                sParam += vHeaderParam.get(i).toString();
                sParam += ", ";

                //System.out.println ();
                //sParam += "\n";
            }
        }
        else {
            i = 0;
        }
        sParam += vHeaderParam.get(i++).toString();
        sParam += "};\n";
        //System.out.println (sParam);
        return sParam;
    }
    /***************************************************************************/
    public Vector createAmplDataFile (String      sTitle,
                                    JTextArea   jta,
                                    MiscellaneaDB portfolioDB,
                                    String      sMuText,
                                    Vector      vReturnSeriesHeader,
                                    Vector      vStocksReturn,
                                    Vector      vTradeDateColumn,
                                    double [][] dReturnSeries) throws Exception
    {
        String sReturnSeriesHeader = null;
        String sStocksReturn       = null;
        String sTradeDateColumn    = null;
	String sReturnSeries       = null;
        Vector vOut                = null;

        try {    
            int iColumn = vReturnSeriesHeader.size ();
            if (iColumn >= 2) {
                //Font normalFont = jta.getFont();
                //Font titleFont = new Font("SansSerif", Font.BOLD|Font.ITALIC, 28);
                jta.append ("\n----------------------------------------------------------\n");
                jta.append (sTitle +"\n");
                jta.append ("----------------------------------------------------------\n");
                
                this.send("option show_stats 1; option display_eps .000001; print $version;\n");
                //jta.setFont(titleFont);
                jta.append (">"+ this.rcv());
                //jta.setFont (normalFont);

                sMuText = "param mu :=" + sMuText + ";";

                sReturnSeriesHeader = this.setAmplSet("A", vReturnSeriesHeader);

                sStocksReturn = this.setAmplSet2 ("K", vStocksReturn);

                sTradeDateColumn = this.setAmplSet("T", vTradeDateColumn);

                sReturnSeries = this.setAmplParam ("R", vReturnSeriesHeader, vTradeDateColumn, dReturnSeries);


//                DataOutputStream output = new DataOutputStream(new FileOutputStream("d:/amplcml/quadmod/Markowitz/test.dat"));
                DataOutputStream output = new DataOutputStream(new FileOutputStream("c:/ampl/quadmod/portfolio.dat"));
                output.writeBytes (sMuText + "\n");
                output.writeBytes (sReturnSeriesHeader + "\n");
                output.writeBytes (sTradeDateColumn + "\n");
                //output.writeBytes (sStocksReturn + "\n");
                output.writeBytes (sReturnSeries + "\n");
                output.close();

//                this.send ("model" + " d:/amplcml/quadmod/markowitz/markowitz.mod" +";\n");
                this.send ("model" + " c:/ampl/quadmod/markowitz.mod" +";\n");
                jta.append (">"+ this.rcv());
                
                //jta.append ("Real returns: " + sStocksReturn + "\n");

                this.send ("printf {j in A} \"%f \",x[j];");

                String sWeights = new String (this.rcv());
                //jta.append ("Fractions: " + sWeights);
                
                vOut = new Vector ();
                for (int i = 0; i < iColumn; i++) {
                    int iSpace = sWeights.indexOf (" ", 0);
                    String sAsset = sWeights.substring(0, iSpace -1);
                    Double DAsset = new Double (sAsset);
                    vOut.add (DAsset);
                    System.out.println (vOut.get(i).toString());
                    sWeights = sWeights.substring(iSpace +1);
                }

                //jta.setFont(titleFont);
//                double [] dWeigths  = new double [iColumn];
//                double [] dReturns  = new double [iColumn];
//                double dPlioReturn  = 0;
//                double dPilotReturn = 0;
//                double dPilotWgth   = (double)1/iColumn;
//                int iIdx  = 0;
//                do {
//                    int iSpace      = sWeights.indexOf(' ');
//                    String W1       = sWeights.substring (0, iSpace);
//                    Double DTmp     = new Double (W1);
//                    dWeigths [iIdx] = DTmp.doubleValue();
//
//                    Double DTmp2    = new Double (vStocksReturn.get(iIdx).toString());
//                    dReturns [iIdx] = DTmp2.doubleValue ();
//
//                    dPlioReturn  += dWeigths [iIdx] * dReturns [iIdx];
//                    dPilotReturn += dPilotWgth      * dReturns [iIdx];
//
//                    jta.append ("Weight"+ iIdx +" "+ dWeigths [iIdx] +"\tHeader: " + dReturns [iIdx] +"  pilot:"+(1/iColumn) +"\n");
//                    sWeights = sWeights.substring (iSpace +1);
//                } while (iIdx++ < iColumn -1);
//
//                jta.append ("Portfolio return:" + dPlioReturn + "\n");
//                jta.append ("PilotPflio return: " + dPilotReturn + "\n");
                this.send ("reset;");
            } /* if (iColumn >= 2) */
            else {
                jta.append ("WARNING: There are not enough stocks to optimize; actual number of stocks in portfolio: " +
                            iColumn +"\n");
            }
        } catch (Exception e) {
            throw new Exception ("Ampl::createAmplDataFile" + e);
        }
        
        return vOut;
    } /*End method createAmplDataFile*/
} /* end Ampl class */
